package auth

import (
	"fmt"
	"strings"

	"gorm.io/gorm"
)

// DataScopeFilter 数据权限过滤器
type DataScopeFilter struct {
}

// DataScopeContext 数据权限上下文
type DataScopeContext struct {
	UserID        uint64
	RoleID        uint64
	DeptID        uint64
	TenantID      uint64
	DataScope     DataScope
	DeptIDs       []uint64
	UserField     string // 用户ID字段名，默认为 "create_by"
	DeptField     string // 部门ID字段名，默认为 "dept_id"
	TenantField   string // 租户ID字段名，默认为 "tenant_id"
	IsSysAdmin    bool   // 是否是系统管理员
	IsTenantAdmin bool   // 是否是租户管理员
	CustomFunc    func(*gorm.DB) *gorm.DB
}

// NewDataScopeFilter 创建数据权限过滤器
func NewDataScopeFilter() *DataScopeFilter {
	return &DataScopeFilter{}
}

// ApplyDataScope 应用数据权限过滤
func (f *DataScopeFilter) ApplyDataScope(db *gorm.DB, ctx *DataScopeContext) *gorm.DB {
	// 设置默认字段名
	if ctx.UserField == "" {
		ctx.UserField = "create_by"
	}
	if ctx.DeptField == "" {
		ctx.DeptField = "dept_id"
	}
	if ctx.TenantField == "" {
		ctx.TenantField = "tenant_id"
	}

	// 如果是系统管理员，不做数据过滤
	if ctx.IsSysAdmin {
		return db
	}

	// 如果是租户管理员，只能看到自己租户的数据
	if ctx.IsTenantAdmin && ctx.TenantID > 0 {
		return db.Where(fmt.Sprintf("%s = ?", ctx.TenantField), ctx.TenantID)
	}

	// 根据数据范围类型添加过滤条件
	switch ctx.DataScope {
	case AllDataScope:
		// 全部数据权限，但仍需限制在当前租户内
		if ctx.TenantID > 0 {
			return db.Where(fmt.Sprintf("%s = ?", ctx.TenantField), ctx.TenantID)
		}
	case DeptDataScope:
		// 本部门数据权限
		if ctx.DeptID > 0 {
			if ctx.TenantID > 0 {
				return db.Where(fmt.Sprintf("%s = ? AND %s = ?", ctx.DeptField, ctx.TenantField),
					ctx.DeptID, ctx.TenantID)
			}
			return db.Where(fmt.Sprintf("%s = ?", ctx.DeptField), ctx.DeptID)
		}
	case DeptAndChildDataScope:
		// 本部门及下级数据权限
		if ctx.DeptID > 0 {
			// 获取部门及其下级部门ID
			subQuery := fmt.Sprintf("SELECT id FROM sys_dept WHERE id = %d OR find_in_set(%d, ancestors)",
				ctx.DeptID, ctx.DeptID)

			if ctx.TenantID > 0 {
				return db.Where(fmt.Sprintf("%s IN (%s) AND %s = ?",
					ctx.DeptField, subQuery, ctx.TenantField), ctx.TenantID)
			}
			return db.Where(fmt.Sprintf("%s IN (%s)", ctx.DeptField, subQuery))
		}
	case SelfDataScope:
		// 仅本人数据权限
		if ctx.UserID > 0 {
			if ctx.TenantID > 0 {
				return db.Where(fmt.Sprintf("%s = ? AND %s = ?",
					ctx.UserField, ctx.TenantField), ctx.UserID, ctx.TenantID)
			}
			return db.Where(fmt.Sprintf("%s = ?", ctx.UserField), ctx.UserID)
		}
	case CustomDataScope:
		// 自定义数据权限
		if len(ctx.DeptIDs) > 0 {
			deptIDs := make([]string, len(ctx.DeptIDs))
			for i, id := range ctx.DeptIDs {
				deptIDs[i] = fmt.Sprintf("%d", id)
			}

			if ctx.TenantID > 0 {
				return db.Where(fmt.Sprintf("%s IN (%s) AND %s = ?",
					ctx.DeptField, strings.Join(deptIDs, ","), ctx.TenantField), ctx.TenantID)
			}
			return db.Where(fmt.Sprintf("%s IN (%s)", ctx.DeptField, strings.Join(deptIDs, ",")))
		}
	}

	// 默认只能看到自己创建的数据
	if ctx.TenantID > 0 {
		return db.Where(fmt.Sprintf("%s = ? AND %s = ?",
			ctx.UserField, ctx.TenantField), ctx.UserID, ctx.TenantID)
	}
	return db.Where(fmt.Sprintf("%s = ?", ctx.UserField), ctx.UserID)
}

// WithDataScope 创建带数据权限的查询构建器
func (f *DataScopeFilter) WithDataScope(ctx *DataScopeContext) func(*gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		return f.ApplyDataScope(db, ctx)
	}
}
